/*
 * Copyright (C) 2017 skydoves
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.skydoves.powermenu;

import com.skydoves.powermenu.kotlin.ContextExtensionsKt;
import com.skydoves.powermenu.shape.ShapeUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.ILifecycle;
import ohos.aafwk.ability.Lifecycle;
import ohos.aafwk.ability.LifecycleStateObserver;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.agp.window.dialog.BaseDialog;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.PopupDialog;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * AbstractPowerMenu is the abstract class of {@link PowerMenu} and {@link CustomPowerMenu}.
 *
 * <p>It implements basically almost things of the PowerMenu.
 *
 * <p>
 */
public abstract class AbstractPowerMenu<E, T extends MenuBaseAdapter<E>>
        implements IMenuItem<E>, LifecycleStateObserver {
    protected DependentLayout backgroundView;
    protected Component menuView;
    protected Component transComponent;
    protected BaseDialog menuWindow;
    protected Lifecycle.Event initializeRule;
    protected ILifecycle iLifecycle;
    protected ListContainer menuListView;
    protected OnMenuItemClickListener<E> menuItemClickListener;
    protected OnDismissedListener onDismissedListener;
    protected LayoutScatter layoutInflater;
    protected DirectionalLayout menuHeaderView;
    protected DirectionalLayout menuFooterView;
    protected boolean isShowBackground = true;
    protected T adapter;
    protected float radius;
    protected int contentViewPadding;
    private int defaultPosition;
    private CircularEffect circularEffect;
    private boolean autoDismiss;
    private boolean dismissIfShowAgain;
    private MenuAnimation menuAnimation;
    private boolean isFocus = false;
    protected final ListContainer.ItemClickedListener itemClickListener =
            new ListContainer.ItemClickedListener() {
                @Override
                public void onItemClicked(ListContainer listContainer, Component component, int index, long l) {
                    if (autoDismiss) {
                        dismiss();
                    }
                    menuItemClickListener.onItemClick(index, (E) getItemList().get(index));
                }
            };
    private final OnMenuItemClickListener<E> onMenuItemClickListener =
            (position, item) -> {
                // empty body
            };

    private float screenX;
    private float screenY;
    private final Component.TouchEventListener onTouchListener = new Component.TouchEventListener() {
        @Override
        public boolean onTouchEvent(Component component, TouchEvent event) {
            if (isFocus) {
                return true;
            }
            // 如果自己接触到了点击，并且不在PopupContentView范围内点击，则进行判断是否是点击事件,如果是，则dismis
            Rect rect = new Rect();
            getGlobalVisibleRect(menuView, rect);
            if (!isInRect(getX(event), getY(event), rect)) {
                switch (event.getAction()) {
                    case TouchEvent.PRIMARY_POINT_DOWN:
                        screenX = getX(event);
                        screenY = getY(event);
                        break;
                    case TouchEvent.PRIMARY_POINT_UP:
                    case TouchEvent.CANCEL:
                        float dx = getX(event) - screenX;
                        float dy = getY(event) - screenY;
                        float distance = (float) Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
                        if (distance < 24) {
                            dismiss();
                        }
                        screenX = 0;
                        screenY = 0;
                        break;
                    default:
                        break;
                }
            }
            return true;
        }
    };

    /**
     * 获取控件的显示区域
     *
     * @param component 控件
     * @param rect      用于存储显示区域的Rect
     * @return 存储了控件显示区域的Rect
     */
    private Rect getGlobalVisibleRect(Component component, Rect rect) {
        int[] locationOnScreen = component.getLocationOnScreen();
        rect.left = locationOnScreen[0];
        rect.right = rect.left + component.getWidth();
        rect.top = locationOnScreen[1];
        rect.bottom = rect.top + component.getHeight();
        return rect;
    }

    private boolean isInRect(float x, float y, Rect rect) {
        return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
    }

    private float getX(TouchEvent touchEvent) {
        return touchEvent.getPointerPosition(0).getX();
    }

    /**
     * 获取相对于偏移位置的y坐标
     *
     * @param touchEvent 触摸事件
     * @return y坐标
     */
    private float getY(TouchEvent touchEvent) {
        return touchEvent.getPointerPosition(0).getY();
    }

    protected AbstractPowerMenu(Context context, AbstractMenuBuilder builder, Component component) {
        transComponent = component;
        isShowBackground = builder.showBackground;
        initialize(context, builder.isMaterial, component);
        menuAnimation = builder.menuAnimation;
        setMenuRadius(builder.menuRadius);
        radius = builder.menuRadius;
        setFocusable(builder.focusable);
        isFocus = builder.focusable;
        setIsClipping(builder.isClipping);
        setDefaultPosition(builder.defaultPosition);
        setDismissIfShowAgain(builder.dismissIfShowAgain);
        if (builder.iLifecycle != null) {
            setILifecycle(builder.iLifecycle);
        } else {
            setILifecycleFromContext(context);
        }
        if (builder.backgroundClickListener != null) {
            setOnBackgroundClickListener(builder.backgroundClickListener);
        }
        if (builder.onDismissedListener != null) {
            setOnDismissedListener(builder.onDismissedListener);
        }
        setWidthAndHeight(builder.width, builder.height);
        if (builder.padding != 0) {
            setPadding(builder.padding);
        }
        if (builder.preferenceName != null) {
            setPreferenceName(builder.preferenceName);
        }
        if (builder.initializeRule != null) {
            setInitializeRule(builder.initializeRule);
        }
        if (builder.circularEffect != null) {
            setCircularEffect(builder.circularEffect);
        }
        if (this.menuWindow instanceof PopupDialog) {
            menuWindow.setCornerRadius(radius);
        }
    }

    protected void initialize(Context context, Boolean isMaterial, Component component) {
        this.layoutInflater = LayoutScatter.getInstance(context);
        this.backgroundView = getMenuBackground(isMaterial);
        if (component != null) {
            transComponent = component;
        }
        this.backgroundView.setTouchEventListener(onTouchListener);
        this.menuView = getMenuRoot(isMaterial);
        this.menuListView = getMenuList(isMaterial);
        this.menuHeaderView = getMenuHeaderView(isMaterial);
        this.menuFooterView = getMenuFooterView(isMaterial);
        if (isShowBackground) {
            this.menuWindow = new CommonDialog(context);
            this.menuWindow.setTransparent(true);
        } else {
            this.menuWindow = new PopupDialog(context, transComponent);
            menuWindow.setTransparent(false);
        }
        setFocusable(isFocus);
        setOnMenuItemClickListener(onMenuItemClickListener);
        contentViewPadding = ConvertUtil.convertDpToPixel(10, context);
        MenuPreferenceManager.initialize(context);
    }

    /**
     * Returns the main root content of the popup menu.
     *
     * @param isMaterial isMaterial
     * @return Component
     */
    abstract Component getMenuRoot(Boolean isMaterial);

    abstract DependentLayout getMenuBackground(Boolean isMaterial);

    abstract DirectionalLayout getMenuHeaderView(Boolean isMaterial);

    abstract DirectionalLayout getMenuFooterView(Boolean isMaterial);

    /**
     * Returns the {@link ListContainer} which constructing the items of the popup menu.
     *
     * @param isMaterial isMaterial
     * @return ListContainer
     */
    abstract ListContainer getMenuList(Boolean isMaterial);

    /**
     * sets {@link ILifecycle} for preventing memory leak.
     *
     * <p>if sets the {@link ILifecycle} this popup will be dismissed automatically
     *
     * <p>when onDestroy method called by lifecycle.
     *
     * @param context {@link Context} which can be the {@link
     *                Ability} or etc are implements {@link
     *                ILifecycle}.
     */
    public void setILifecycleFromContext(Context context) {
        if (context instanceof ILifecycle) {
            setILifecycle((ILifecycle) context);
        }
    }

    /**
     * sets the corner radius of the popup menu.
     *
     * @param radius corner radius.
     */
    public void setMenuRadius(float radius) {
        menuView.setBackground(ShapeUtil.createDrawable(0xffffffff, radius));
    }

    /**
     * sets {@link ILifecycle} for preventing memory leak.
     *
     * <p>if sets the {@link ILifecycle} this popup will be dismissed automatically
     *
     * <p>when onDestroy method called by lifecycle.
     *
     * @param iLifecycle {@link Ability} or etc are implements {@link
     *                   ILifecycle}.
     */
    public void setILifecycle(ILifecycle iLifecycle) {
        iLifecycle.getLifecycle().addObserver(this);
        this.iLifecycle = iLifecycle;
    }

    /**
     * makes focusing only on the menu popup.
     *
     * @param focusable focusable or not.
     */
    public void setFocusable(boolean focusable) {
    }

    /**
     * gets onMenuItemClickListener.
     *
     * @return {@link OnMenuItemClickListener}.
     */
    public OnMenuItemClickListener<E> getOnMenuItemClickListener() {
        return this.menuItemClickListener;
    }

    /**
     * sets {@link OnMenuItemClickListener}.
     *
     * @param menuItemClickListener menu item click listener.
     */
    public void setOnMenuItemClickListener(OnMenuItemClickListener<E> menuItemClickListener) {
        this.menuItemClickListener = menuItemClickListener;
        this.menuListView.setItemClickedListener(itemClickListener);
    }

    public void showAtCenter(Component anchor) {
        Runnable function = () -> {
            menuWindow.show();
        };
        showPopup(anchor, function);
    }

    /**
     * showing the popup menu as drop down to the anchor.
     *
     * @param anchor anchor view.
     */
    public void showAsDropDown(final Component anchor) {
        Runnable function = () -> menuWindow.show();
        showPopup(anchor, function);
    }

    /**
     * showing the popup menu as drop down to the anchor with x-off and y-off.
     *
     * @param anchor anchor view.
     * @param xOff   x-off,
     * @param yOff   y-off.
     */
    public void showAsDropDown(final Component anchor, final int xOff, final int yOff) {
        Runnable function = () -> {
            setMenuTranslate(anchor, xOff, yOff);
            menuWindow.show();
        };
        showPopup(anchor, function);
    }

    public void showTransAsAnchor(Component anchor, int xoff, int yoff) {
        ((PopupDialog) menuWindow).showOnCertainPosition(LayoutAlignment.TOP, xoff, yoff);
    }

    public void showLocation(Component anchor) {
        Runnable function = () -> {
            if (menuWindow instanceof CommonDialog) {
                setMenuTranslate(anchor, 0, 0);
                int select = MenuPreferenceManager.getInstance().getPosition(getAdapter().getPreferenceName(), 0);
                if (getItemList() != null) {
                    for (int i = 0; i < getItemList().size(); i++) {
                        PowerMenuItem item = (PowerMenuItem) getItemList().get(i);
                        item.setIsSelected(false);
                        if (i == select) {
                            item.setIsSelected(true);
                        }
                    }
                }
                getAdapter().notifyDataChanged();
                menuWindow.show();
            }
        };
        showPopup(anchor, function);
    }

    int xOff;
    int yOff;

    private void setMenuTranslate(Component anchor, int xOff, int yOff) {
        int[] locations = anchor.getLocationOnScreen();
        this.xOff = locations[0] + xOff;
        this.yOff = locations[1] + yOff;

        menuView.setTranslation(this.xOff, this.yOff);
    }

    /**
     * showing the popup to the anchor.
     *
     * @param anchor   anchor view.
     * @param function runnable.
     * @return Builder
     */
    private void showPopup(final Component anchor, final Runnable function) {
        if (!isShowing()
                && anchor.isBoundToWindow()
                && !ContextExtensionsKt.isFinishing(anchor.getContext())
        ) {
            doMenuEffect();
            function.run();
        } else if (this.dismissIfShowAgain) {
            dismiss();
        }
    }

    /**
     * apply menu effect.
     */
    private void doMenuEffect() {
        if (getCircularEffect() != null) {
            if (getCircularEffect().equals(CircularEffect.BODY)) {
                circularRevealed(menuView);
            } else if (getCircularEffect().equals(CircularEffect.INNER)) {
                circularRevealed(getListView());
            }
        }
    }

    boolean isAnimated = false;

    /**
     * shows circular revealed animation to a view.
     *
     * @param targetView view for animation target.
     */
    private void circularRevealed(Component targetView) {
        targetView.setLayoutRefreshedListener(new Component.LayoutRefreshedListener() {
            @Override
            public void onRefreshed(Component component) {
                Animator animator = null;
                switch (menuAnimation) {
                    case SHOWUP_TOP_LEFT:
                        component.setScale(0.2f, 0.2f);
                        animator = new AnimatorGroup();
                        ((AnimatorGroup) animator).runSerially(transAnim(component), scaleAnim(component, 0.2f, 0.2f, 1, 1, 150));
                        break;
                    case FADE:
                        animator = alphaAnim(component, 0.0f, 1.0f, 200);
                        break;
                    case SHOW_UP_CENTER:
                        animator = scaleAnim(component, 0.0f, 0.0f, 1, 1, 200);
                        break;
                    case ELASTIC_CENTER:
                        animator = scaleAnim(component, 0.0f, 0.0f, 1f, 1f, 1500)
                                .setCurveType(Animator.CurveType.ACCELERATE | Animator.CurveType.BOUNCE);
                        break;
                }
                animator.start();
            }
        });
    }

    private AnimatorProperty transAnim(Component component) {
        AnimatorProperty an1 = component.createAnimatorProperty()
                .moveFromX(0).moveToX(xOff)
                .moveFromY(0).moveToY(yOff)
                .setDuration(50);
        return an1;
    }

    private AnimatorProperty scaleAnim(Component component, float scalxFrom, float scaleyFrom, float scalex, float scaley, int duration) {
        return component.createAnimatorProperty().scaleXFrom(scalxFrom).scaleX(scalex).scaleYFrom(scaleyFrom).scaleY(scaley).setDuration(duration);
    }

    private AnimatorProperty alphaAnim(Component component, float alphaFrom, float alpha, int duration) {
        return component.createAnimatorProperty().alphaFrom(alphaFrom).alpha(alpha).setDuration(duration);
    }

    /**
     * dismiss the popup menu.
     */
    public void dismiss() {
        if (isShowing()) {
            AnimatorProperty disAnim = null;
            switch (menuAnimation) {
                case SHOWUP_TOP_LEFT:
                    disAnim = scaleAnim(menuView, 1f, 1f, 0.2f, 0.2f, 150);
                    break;
                case FADE:
                    disAnim = alphaAnim(menuView, 1.0f, 0.0f, 150);
                    break;
                case SHOW_UP_CENTER:
                    disAnim = scaleAnim(menuView, 1f, 1f, 0.2f, 0.2f, 200);
                    break;
                case ELASTIC_CENTER:
                    disAnim = scaleAnim(menuView, 1f, 1f, 0.2f, 0.2f, 100);
                    break;
                case SHOWUP_TOP_RIGHT:
                    this.menuWindow.destroy();
                    if (this.onDismissedListener != null) {
                        this.onDismissedListener.onDismissed();
                    }
                    break;
            }
            if (disAnim == null) {
                return;
            }
            disAnim.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                    menuWindow.destroy();
                    {
                        if (onDismissedListener != null) {
                            onDismissedListener.onDismissed();
                        }
                    }
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            });
            disAnim.start();
        }
    }

    /**
     * gets the popup is showing or not.
     *
     * @return the popup is showing or not.
     */
    public boolean isShowing() {
        return this.menuWindow.isShowing();
    }

    /**
     * gets the content view padding of the popup menu.
     *
     * @return the content view padding view of the popup menu.
     */
    protected int getContentViewPadding() {
        return this.contentViewPadding;
    }

    /**
     * sets the width of the popup menu.
     *
     * @param width  width of the popup menu.
     * @param height height of the popup menu.
     * @return Builder
     */
    public void setWidthAndHeight(int width, int height) {
        if (width == 0) {
            width = DirectionalLayout.LayoutConfig.MATCH_CONTENT;
        }
        if (height == 0) {
            height = DirectionalLayout.LayoutConfig.MATCH_CONTENT;
        }
        ComponentContainer.LayoutConfig layoutConfig = menuView.getLayoutConfig();
        layoutConfig.width = width;
        layoutConfig.height = height;
        menuView.setLayoutConfig(layoutConfig);
    }

    /**
     * 获取屏幕宽度
     *
     * @param context 上下文
     * @return 屏幕宽度，单位px
     */
    private int getWindowWdith(Context context) {
        return context.getResourceManager().getDeviceCapability().width * context.getResourceManager().getDeviceCapability().screenDensity / 160;
    }

    /**
     * 获取屏幕宽度
     *
     * @param context 上下文
     * @return 屏幕宽度，单位px
     */
    private int getWindowHeight(Context context) {
        return context.getResourceManager().getDeviceCapability().height * context.getResourceManager().getDeviceCapability().screenDensity / 160;
    }

    /**
     * sets a padding size of the popup menu.
     *
     * @param padding padding size.
     */
    public void setPadding(int padding) {
        this.menuListView.setPadding(padding, padding, padding, padding);
    }

    /**
     * sets the dismissed listener of the popup menu.
     *
     * @param onDismissedListener {@link OnDismissedListener}.
     */
    public void setOnDismissedListener(OnDismissedListener onDismissedListener) {
        this.onDismissedListener = onDismissedListener;
    }

    /**
     * sets the background click listener of the background.
     *
     * @param onBackgroundClickListener {@link Component.ClickedListener}.
     */
    public void setOnBackgroundClickListener(Component.ClickedListener onBackgroundClickListener) {
        this.backgroundView.setClickedListener(onBackgroundClickListener);
    }

    /**
     * sets custom animations of the popup. It will start up when the popup is showing.
     *
     * @param style custom animation style.
     */
    public void setAnimationStyle(int style) {
    }

    /**
     * sets the clipping enable or unable.
     *
     * @param isClipping clipping enable or unable.
     */
    public void setIsClipping(boolean isClipping) {
    }

    /**
     * sets the selected position of the popup menu. It can be used for scrolling as the position.
     *
     * @param position selected position.
     */
    public void setSelection(int position) {
    }

    /**
     * check validation of the initialization from the preference persistence.
     *
     * @param event lifecycle event.
     * @return true or false.
     */
    private boolean checkRuleValidates(Lifecycle.Event event) {
        return getInitializeRule() != null && getInitializeRule().equals(event);
    }

    /**
     * invokes onMenuListener manually.
     *
     * @param position the invoked position.
     */
    public void invokeOnMenuListener(int position) {
        if (position >= 0 && position < getItemList().size() && getOnMenuItemClickListener() != null) {
            getOnMenuItemClickListener().onItemClick(
                    getPreferencePosition(position), getItemList().get(getPreferencePosition(position)));
        }
    }

    public void onStart() {
        if (checkRuleValidates(Lifecycle.Event.ON_START)) {
            invokeOnMenuListener(defaultPosition);
        }
    }

    public void onResume() {
        if (checkRuleValidates(Lifecycle.Event.ON_ACTIVE)) {
            invokeOnMenuListener(defaultPosition);
        }
    }

    public void onDestroy() {
        dismiss();
    }

    /**
     * gets the adapter of the popup menu list.
     *
     * @return adapter
     */
    public T getAdapter() {
        return this.adapter;
    }

    @Override
    public void addItem(E item) {
        getAdapter().addItem(item);
    }

    @Override
    public void addItem(int position, E item) {
        getAdapter().addItem(position, item);
    }

    @Override
    public void addItemList(List<E> itemList) {
        getAdapter().addItemList(itemList);
    }

    @Override
    public ListContainer getListView() {
        return getAdapter().getListView();
    }

    @Override
    public void setListView(ListContainer listView) {
        getAdapter().setListView(getMenuListView());
    }

    @Override
    public int getSelectedPosition() {
        return getAdapter().getSelectedPosition();
    }

    @Override
    public void setSelectedPosition(int position) {
        getAdapter().setSelectedPosition(position);
    }

    @Override
    public void removeItem(E item) {
        getAdapter().removeItem(item);
    }

    @Override
    public void removeItem(int position) {
        getAdapter().removeItem(position);
    }

    @Override
    public void clearItems() {
        getAdapter().clearItems();
    }

    @Override
    public List<E> getItemList() {
        return getAdapter().getItemList();
    }

    /**
     * gets the {@link ListContainer} of the popup menu.
     *
     * @return {@link ListContainer}.
     */
    public ListContainer getMenuListView() {
        return this.menuListView;
    }

    /**
     * gets the header view of the popup menu list.
     *
     * @return {@link Component}.
     */
    public Component getHeaderView() {
        return menuHeaderView;
    }

    /**
     * gets the footer view of the popup menu list.
     *
     * @return {@link Component}.
     */
    public Component getFooterView() {
        return menuFooterView;
    }

    /**
     * sets the auto-dismissing or not.
     *
     * <p>The popup menu will be dismissed automatically when the item would be clicked.
     *
     * @param autoDismiss is auto-dismissing or not.
     */
    public void setAutoDismiss(boolean autoDismiss) {
        this.autoDismiss = autoDismiss;
    }

    /**
     * sets the dismiss action if already popup is showing.
     *
     * @param dismissIfShowAgain dismiss if already popup is showing.
     */
    public void setDismissIfShowAgain(boolean dismissIfShowAgain) {
        this.dismissIfShowAgain = dismissIfShowAgain;
    }

    /**
     * gets the preference name of PowerMenu.
     *
     * @return preference name.
     */
    public String getPreferenceName() {
        return getAdapter().getPreferenceName();
    }

    /**
     * gets the saved preference position from the SharedPreferences.
     *
     * @param defaultPosition the default position of the preference.
     * @return saved preference position.
     */
    public int getPreferencePosition(int defaultPosition) {
        return MenuPreferenceManager.getInstance()
                .getPosition(getAdapter().getPreferenceName(), defaultPosition);
    }

    /**
     * sets the preference position name for persistence.
     *
     * @param defaultPosition the default position of the preference.
     */
    public void setPreferencePosition(int defaultPosition) {
        MenuPreferenceManager instance = MenuPreferenceManager.getInstance();
        if (instance != null && getPreferenceName() != null) {
            instance.setPosition(getPreferenceName(), defaultPosition);
        }
    }

    /**
     * sets a preference name for persistence.
     *
     * @param preferenceName preference name.
     */
    private void setPreferenceName(String preferenceName) {
        getAdapter().setPreference(preferenceName);
    }

    /**
     * clears the preference name of PowerMenu.
     */
    public void clearPreference() {
        if (getAdapter().getPreferenceName() != null) {
            MenuPreferenceManager.getInstance().clearPosition(getAdapter().getPreferenceName());
        }
    }

    /**
     * sets initialize rule by {@link Lifecycle.Event}.
     *
     * <p>There are three events(ON_CREATE, ON_START, ON_RESUME) working by lifecycle.
     *
     * @param event {@link Lifecycle.Event}.
     */
    private void setInitializeRule(Lifecycle.Event event) {
        this.initializeRule = event;
    }

    /**
     * gets initialize rule by {@link Lifecycle.Event}.
     *
     * @return {@link Lifecycle.Event}.
     */
    private Lifecycle.Event getInitializeRule() {
        return this.initializeRule;
    }

    /**
     * sets the default position from the persistence.
     *
     * @param defaultPosition default position.
     */
    private void setDefaultPosition(int defaultPosition) {
        this.defaultPosition = defaultPosition;
    }

    /**
     * gets menu effect.
     *
     * @return {@link CircularEffect}.
     */
    public CircularEffect getCircularEffect() {
        return this.circularEffect;
    }

    /**
     * sets menu effects for showing popup more dynamically.
     *
     * @param circularEffect {@link CircularEffect}.
     */
    public void setCircularEffect(CircularEffect circularEffect) {
        this.circularEffect = circularEffect;
    }
}
